from fastapi import FastAPI
from tortoise.contrib.fastapi import register_tortoise
from blog.routers import articles, tags, categories, comments, notifications, auth
from . import settings
import logging
import sys
import os
import base64, binascii
import casbin
from starlette.authentication import AuthenticationBackend, AuthenticationError, SimpleUser, AuthCredentials
from starlette.middleware.authentication import AuthenticationMiddleware
from fastapi_authz import CasbinMiddleware
from fastapi_pagination import add_pagination
from .signals import create_notification #此处引入后，信号处理才会生效
from fastapi.middleware.cors import CORSMiddleware
from blog.utils import verify_token

app = FastAPI()

app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"],allow_headers=["*"])


# 添加acl中间件
class BasicAuth(AuthenticationBackend):
    async def authenticate(self, request):
        if "Authorization" not in request.headers:
            return None

        auth = request.headers["Authorization"]
        _, token = auth.split()
        if not verify_token(token):
            return None
        return AuthCredentials(["authenticated"]), SimpleUser(settings.ADMIN_USERNAME)

base_dir = os.path.dirname(os.path.abspath(__file__))
enforcer = casbin.Enforcer(os.path.join(base_dir, "rbac", "model.conf"), os.path.join(base_dir, "rbac", "policy.csv"))

app.add_middleware(CasbinMiddleware, enforcer=enforcer)
app.add_middleware(AuthenticationMiddleware, backend=BasicAuth())

app.include_router(auth.router)
app.include_router(articles.router)
app.include_router(tags.router)
app.include_router(categories.router)
app.include_router(comments.router)
app.include_router(notifications.router)

# test video serve 
# @app.get("/video")
# async def video_endpoint(range: str = Header(None)):
#     CHUNK_SIZE = 1024*1024
#     from pathlib import Path
#     video_path = Path("D:\\bilibiliDownload\\gundam00mad.mp4")
#     start, end = range.replace("bytes=", "").split("-")
#     start = int(start)
#     end = int(end) if end else start + CHUNK_SIZE
#     with open(video_path, "rb") as video:
#         video.seek(start)
#         data = video.read(end - start)
#         filesize = str(video_path.stat().st_size)
#         headers = {
#             'Content-Range': f'bytes {str(start)}-{str(end)}/{filesize}',
#             'Accept-Ranges': 'bytes'
#         }
#         return Response(data, status_code=206, headers=headers, media_type="video/mp4")

# tortoise logging
fmt = logging.Formatter(
    fmt="%(asctime)s - %(name)s:%(lineno)d - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)
sh = logging.StreamHandler(sys.stdout)
sh.setLevel(logging.DEBUG)
sh.setFormatter(fmt)
logger_db_client = logging.getLogger("db_client")
logger_db_client.setLevel(logging.DEBUG)
logger_db_client.addHandler(sh)

logger_tortoise = logging.getLogger("tortoise")
logger_tortoise.setLevel(logging.DEBUG)
logger_tortoise.addHandler(sh)

register_tortoise(
    app,
    config=settings.TORTOISE_ORM,
    add_exception_handlers=True,
)

add_pagination(app)